package com.quarkus.resources;

import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

/**
 * @Author: TongRui乀
 * @Date: 2020/12/5 16:08
 * @description：
 */
@Path("rx")
public class ReactiveResources {

    @Path("hello")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(){
        return "hello";
    }

    @GET
    @Path("uni_test1")
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> uni_test(){
        return Uni.createFrom().item("uni");
    }

    @GET
    @Path("uni_test2")
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> uni_test2(){
        return Uni.createFrom().item(()->{return "hello uni";});
    }

    @GET
    @Path("uni_test3")
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> uni_test3(){

        return Uni.createFrom().completionStage(CompletableFuture
                .supplyAsync(()->"hello ")
                .thenApply(str->{return str + "completeStage";}));
    }

    @GET
    @Path("uni_test4")
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> uni_test4(){
        return Uni.createFrom().failure(RuntimeException::new);
    }


    @GET
    @Path("uni_test5")
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<String> uni_test5(){

        return Uni.createFrom().multi(Multi
                                        .createFrom()
                                        .items(Stream.of("1", "2")));
    }

    @GET
    @Path("multi_test1")
    @Produces(MediaType.APPLICATION_JSON)
    public Multi<String> multi_test1(){

        return Multi.createFrom().items(Stream.of("1", "2", "3"));
    }

    @GET
    @Path("multi_test2")
    @Produces(MediaType.APPLICATION_JSON)
    public Multi<String> multi_test2(){

        return Uni.createFrom().item(Arrays.asList("1", "2", "3"))
                .onItem()
                .transformToMulti(list-> Multi.createFrom().items(list.stream()));
    }

    /**
     * @Description:
     * @param @param  toUni 只会取第一个item
     * @return @return
     * @author TongRui乀
     * @throws
     * @date 2021/1/10 7:43 下午
     */
    @GET
    @Path("multi_test3")
    @Produces(MediaType.APPLICATION_JSON)
    public Uni<String> multi_test3(){

        return Uni.createFrom().item(Arrays.asList("1", "2", "3"))
                .onItem()
                .transformToMulti(list-> Multi.createFrom().items(list.stream()))
                .toUni();
    }

    @GET
    @Path("multi_test4")
    @Produces(MediaType.APPLICATION_JSON)
    public Multi<Integer> multi_test4(){

        return Multi.createFrom().items(1,2,4,5)
                .onItem()
                .transformToUniAndConcatenate(num-> Uni.createFrom().item(num * 2));
    }

    @GET
    @Path("multi_test5")
    @Produces(MediaType.APPLICATION_JSON)
    public Multi<Integer> multi_test5(){

        return Multi.createFrom().items(1,2,4,5)
                .onItem()
                .transformToUniAndMerge(num-> Uni.createFrom().item(num*2));
    }


    @GET
    @Path("multi_test6")
    @Produces(MediaType.APPLICATION_JSON)
    public Multi<Integer> multi_test6(){

        return Multi.createBy().repeating()
                .uni(AtomicInteger::new, atomicInteger -> {
                    atomicInteger.getAndIncrement();
                    int num = atomicInteger.get();
                    if(num == 10){
                        return Uni.createFrom().item(Collections.emptyList());
                    }
                    List<Integer> res = Collections.singletonList(num);
                    return Uni.createFrom().item(res);
                })
                .until(List::isEmpty)
                .onItem()
                .disjoint();
    }


}
